/******************************************
 * @Author:RNF
 * @Date:2024-07-28 00:24:30
 * @LastEditTime:2024-07-28 15:27:54
 * @LastEditors:XG
 * @Description:
 * @FilePath:\STM32Fans\User\button.c
 * @桃之夭夭
 ******************************************/
/**************************************************************************************************
 * fuction	:                              button
 * file		:  button.c
 * brief		:
 * author	: rinanfang  3/2/2020
 **************************************************************************************************/

#define __BUTTON_C__

/* ------------------------------------------- include ----------------------------------------- */
#include "button.h"

// 函数声明
uint8_t read_hot_up_level(void);
uint8_t read_hot_down_level(void);
uint8_t read_ice_up_level(void);
uint8_t read_ice_down_level(void);
uint8_t read_motor_up_level(void);
uint8_t read_motor_down_level(void);

void hot_up_down_callback(void* btn);
void hot_down_down_callback(void* btn);
void ice_up_down_callback(void* btn);
void ice_down_down_callback(void* btn);
void motor_up_down_callback(void* btn);
void motor_down_down_callback(void* btn);
// 长按回调的前置声明
void hot_up_long_callback(void* btn);
void ice_up_long_callback(void* btn);
void motor_up_long_callback(void* btn);

/* ------------------------------------- define/typedef/enum ----------------------------------- */

/* ------------------------------------------- variable ---------------------------------------- */
// Button's head
static struct button* head_button = NULL;

/* -------------------------------------------static funtion ----------------------------------------- */
// Name str copy
static char* strn_copy(char* dst, const char* src, unsigned int n);
static void  button_cycle_process(button_t* btn);

// read sw level || sw event callback
////需要修改的函数声明
// static uint8_t 	Read_SW0_Level (void);

/* -------------------------------------------global funtion ----------------------------------------- */
// main button function
//  extern void Button_Attach_ini (void);

/* -------------------------------------------modify funtion ----------------------------------------- */

// 新的6个按键
button_t sw20;  // PA8
button_t sw21;  // PA11
button_t sw22;  // PA12
button_t sw23;  // PA15
button_t sw24;  // PB3
button_t sw25;  // PB15
#include "main.h"
#include "my_define.h"
// 新的6个按键的读取函数
uint8_t read_hot_up_level(void)  // PA8
{
  GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_3);
  return (pinState == GPIO_PIN_SET) ? 0 : 1;

}

uint8_t read_hot_down_level(void)  // PA11
{
  GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_15);
  return (pinState == GPIO_PIN_SET) ? 0 : 1;
}

uint8_t read_ice_up_level(void)  // PA12
{
    GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_12);
    return (pinState == GPIO_PIN_SET) ? 0 : 1;
}

uint8_t read_ice_down_level(void)  // PA15
{

    GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_11);
    return (pinState == GPIO_PIN_SET) ? 0 : 1;
}

uint8_t read_motor_up_level(void)  // PB3
{
  GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8);
  return (pinState == GPIO_PIN_SET) ? 0 : 1;
}

uint8_t read_motor_down_level(void)  // PB15
{
    GPIO_PinState pinState = HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_15);
    return (pinState == GPIO_PIN_SET) ? 0 : 1;
}
// 新的6个按键的回调函数
//hot temperture 
void hot_up_long_callback(void* btn)  
{

}
void hot_up_down_callback(void* btn) 
{

}
void hot_down_down_callback(void* btn) 
{

}
//ice temperture
void ice_up_long_callback(void* btn)  
{

}
void ice_up_down_callback(void* btn)  
{

}
void ice_down_down_callback(void* btn)  
{

}
//motor speed control
void motor_up_long_callback(void* btn)  
{

}
void motor_up_down_callback(void* btn) 
{

}
void motor_down_down_callback(void* btn) 
{

}
// 按键链接初始化
void button_attach_init(void)
{
    // 注册新的6个按键
    button_create("sw20", &sw20, read_hot_up_level);
    button_attach(&sw20, BUTTON_DOWN, hot_up_down_callback);
    button_attach(&sw20, BUTTON_LONG, hot_up_long_callback);
    button_create("sw21", &sw21, read_hot_down_level);
    button_attach(&sw21, BUTTON_DOWN, hot_down_down_callback);
    button_create("sw22", &sw22, read_ice_up_level);
    button_attach(&sw22, BUTTON_DOWN, ice_up_down_callback);
    button_attach(&sw22, BUTTON_LONG, ice_up_long_callback);
    button_create("sw23", &sw23, read_ice_down_level);
    button_attach(&sw23, BUTTON_DOWN, ice_down_down_callback);
    button_create("sw24", &sw24, read_motor_up_level);
    button_attach(&sw24, BUTTON_DOWN, motor_up_down_callback);
    button_attach(&sw24, BUTTON_LONG, motor_up_long_callback);
    button_create("sw25", &sw25, read_motor_down_level);
    button_attach(&sw25, BUTTON_DOWN, motor_down_down_callback);
}

/* -------------------------------------------modify end ----------------------------------------- */

/* ------------------------------------------- funtion ----------------------------------------- */
// 内部函数
/* ------------------------------------------- funtion ----------------------------------------- */
/************************************************************
 * @brief   按键周期处理函数
 * @param   btn:处理的按键
 * @return  NULL
 * @author  jiejie
 * @github  https://github.com/jiejieTop
 * @date    2018-xx-xx
 * @version v1.0
 * @note    必须以一定周期调用此函数，建议周期为20~50ms
 ***********************************************************/
void button_cycle_process(button_t* btn)
{
    uint8_t current_level = (uint8_t)btn->Read_Button_Level();
    // 按键电平发生变化，消抖
    if ((current_level != btn->Button_Last_Level) && (++(btn->level_timercnt) > BUTTON_LEVEL_STABLE))
    {
        btn->Button_Last_Level = current_level;  // 更新当前按键电平
        btn->level_timercnt    = 0;              // 确定了是按下

        // 如果按键是没被按下的，改变按键状态为按下(首次按下/双击按下)
        if (btn->Button_State == NONE_TRIGGER && btn->Button_Last_Level == btn->Button_Trigger_Level)
        {
            btn->Button_State = BUTTON_DOWN;
        }
        // 释放按键
        else if (btn->Button_State == BUTTON_DOWN)
        {
            btn->Button_State = BUTTON_UP;
        }
        // 双击检测
#if SINGLE_AND_DOUBLE_TRIGGER == 1
        else if (btn->Button_State == BUTTON_DOUBLE_WAIT)
        {
            btn->Button_State = BUTTON_DOWN;
        }
#endif
    }
    else if (current_level == btn->Button_Last_Level)
    {
        // 重置消抖寄存器
        btn->level_timercnt = 0;
    }

    switch (btn->Button_State)
    {
    case BUTTON_DOWN:  // 按下状态
    {
        // 按键按下电平和我们设置电平相一致时
        if (btn->Button_Last_Level == btn->Button_Trigger_Level)
        {
// 连按
#if CONTINUOS_TRIGGER

            if (++(btn->cycle_timercnt) >= BUTTON_CONTINUOS_CYCLE)
            {
                btn->cycle_timercnt       = 0;
                btn->Button_Trigger_Event = BUTTON_CONTINUOS;
                TRIGGER_CB(BUTTON_CONTINUOS);  // 连按
                // PRINT_DEBUG("连按");
            }

#else
            // 按下定时器计数
            btn->down_timecnt++;

            // 单击
            if (btn->down_timecnt < BUTTON_LONG_TIME && btn->Button_Trigger_Event != BUTTON_DOUBLE_WAIT)
            {
                btn->Button_Trigger_Event = BUTTON_DOWN;
            }
// 长按释放
#if LONG_FREE_TRIGGER == 1
            else if (btn->Long_Time == BUTTON_LONG_TIME)
            {
                btn->Button_Trigger_Event = BUTTON_LONG_FREE;
            }
#else
            // 长按
            else if (btn->down_timecnt == BUTTON_LONG_TIME)  // 释放按键前更新触发事件为长按
            {
                btn->Button_Trigger_Event = BUTTON_LONG;
                TRIGGER_CB(BUTTON_LONG);  // 第一次长按
            }

            // 长按后
            else if (btn->down_timecnt > BUTTON_LONG_TIME)
            {
                if (++(btn->cycle_timercnt) >= BUTTON_LONG_CYCLE)  // 连续触发长按的周期
                {
                    btn->cycle_timercnt       = 0;
                    btn->Button_Trigger_Event = BUTTON_LONG;
                    TRIGGER_CB(BUTTON_LONG);  // 长按连续触发
                }
            }
#endif
            // 更新按下计数器时间
            if (btn->down_timecnt == 0xFF)
            {
                // 更新长按后
                btn->down_timecnt = BUTTON_LONG_TIME + 1;
            }
        }

#endif

            break;
        }

    case BUTTON_UP:  // 弹起状态
    {
        // 触发单击
        if (btn->Button_Trigger_Event == BUTTON_DOWN)
        {
            // 单击
#if (SINGLE_AND_DOUBLE_TRIGGER == 0)
            TRIGGER_CB(BUTTON_DOWN);
            btn->down_timecnt         = 0;
            btn->Button_State         = NONE_TRIGGER;
            btn->Button_Trigger_Event = NONE_TRIGGER;
#else
            // 双击检测
            if (btn->Button_Trigger_Event == BUTTON_DOWN)
            {
                btn->down_timecnt         = 0;
                btn->cycle_timercnt       = 0;
                btn->double_timecnt       = 0;
                btn->Button_State         = BUTTON_DOUBLE_WAIT;
                btn->Button_Trigger_Event = BUTTON_DOUBLE_WAIT;
            }
            else if (btn->Button_Trigger_Event == BUTTON_DOUBLE_WAIT)
            {
                // 双击检测
                btn->down_timecnt   = 0;
                btn->cycle_timercnt = 0;
                btn->double_timecnt = 0;
                TRIGGER_CB(BUTTON_DOUBLE);
                btn->Button_Last_State    = BUTTON_DOUBLE;
                btn->Button_State         = NONE_TRIGGER;
                btn->Button_Trigger_Event = NONE_TRIGGER;
            }
#endif
        }
        else if (btn->Button_Trigger_Event == BUTTON_CONTINUOS)
        {
            btn->down_timecnt   = 0;
            btn->cycle_timercnt = 0;
            // 在按下那边已经触发了
            btn->Button_State         = NONE_TRIGGER;
            btn->Button_Trigger_Event = NONE_TRIGGER;
        }
        // 长按
        else if (btn->Button_Trigger_Event == BUTTON_LONG)
        {
            TRIGGER_CB(BUTTON_LONG_FREE);
            btn->down_timecnt   = 0;
            btn->cycle_timercnt = 0;
            // 在按下那边已经触发了
            btn->Button_State         = NONE_TRIGGER;
            btn->Button_Trigger_Event = NONE_TRIGGER;
        }
#if LONG_FREE_TRIGGER == 1
        // 长按释放
        else if (btn->Button_Trigger_Event == BUTTON_LONG_FREE)
        {
            TRIGGER_CB(BUTTON_LONG_FREE);
            btn->down_timecnt   = 0;
            btn->cycle_timercnt = 0;
            // 在按下那边已经触发了
            btn->Button_Last_State    = BUTTON_LONG_FREE;
            btn->Button_State         = NONE_TRIGGER;
            btn->Button_Trigger_Event = NONE_TRIGGER;
        }
#endif
#if CONTINUOS_TRIGGER
        else if (btn->Button_Trigger_Event == BUTTON_CONTINUOS)  // 连按
        {
            btn->Long_Time = 0;
            TRIGGER_CB(BUTTON_CONTINUOS_FREE);  // 连发释放
            btn->Button_State      = NONE_TRIGGER;
            btn->Button_Last_State = BUTTON_CONTINUOS;
        }
#endif

        break;
    }
// 双击检测
#if (SINGLE_AND_DOUBLE_TRIGGER == 1)
    case BUTTON_DOUBLE_WAIT:  // 双击中间间隔的超时判断
    {
        btn->double_timecnt++;  // 时间记录
        // 超时
        if (btn->double_timecnt >= BUTTON_DOUBLE_TIME)
        {
            btn->double_timecnt       = 0;
            btn->Button_Trigger_Event = BUTTON_DOWN;
            TRIGGER_CB(BUTTON_DOWN);
            btn->Button_State         = NONE_TRIGGER;
            btn->Button_Trigger_Event = NONE_TRIGGER;
        }
        break;
    }
#endif

    default:
        break;
    }
    }

    /**************************************************************************************************
     * function	:                                   Button_Process
     * brief	:  			   scan each button and each button's each button event
     * param	:  			   none
     * return			:  none
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    void button_process(void)
    {
        struct button* pass_btn;
        for (pass_btn = head_button; pass_btn != NULL; pass_btn = pass_btn->Next)
        {
            button_cycle_process(pass_btn);
        }
    }

    /**************************************************************************************************
     * function	:                                   Add_Button
     * brief	:   add button node to button linear list
     * param	:  button node
     * return			:  none
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    void add_button(button_t * btn)
    {
        struct button* pass_btn = head_button;

        while (pass_btn)
        {
            pass_btn = pass_btn->Next;
        }

        btn->Next   = head_button;
        head_button = btn;
    }

    /**************************************************************************************************
     * function	:                                   Button_Delete
     * brief	:  delete button node from button linear list
     * param	:  button node
     * return			:  none
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    void button_delete(button_t * btn)
    {
        struct button** curr;
        for (curr = &head_button; *curr;)
        {
            struct button* entry = *curr;
            if (entry == btn)
            {
                *curr = entry->Next;
            }
            else
            {
                curr = &entry->Next;
            }
        }
    }
    /**************************************************************************************************
     * function	:                                   Button_Create
     * brief	:  create a new button nod and add it to button linear list
     * param	:  button name||button node||button level||button trigger level
     * return			:  TRUE FALSE
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    boolean_t button_create(const char* name, button_t* btn, uint8_t (*read_btn_level)(void))
    {
        if (btn == NULL)
        {
            return FALSE;
        }
        //"string.h"
        memset(btn, 0, sizeof(struct button));  //
        strn_copy(btn->Name, name, BTN_NAME_MAX);

        // set button param to no trigger status
        btn->Button_State         = NONE_TRIGGER;    // 按键状态
        btn->Button_Trigger_Event = NONE_TRIGGER;    // 按键触发事件
        btn->Read_Button_Level    = read_btn_level;  // 按键读电平函数
        //	  btn->Button_Trigger_Level = HIGHT;  //按键触发电平
        //	  btn->Button_Last_Level = LOW; 			//按键当前电平
        btn->Button_Trigger_Level = HIGHT;                     // 按键触发电平
        btn->Button_Last_Level    = btn->Read_Button_Level();  // 按键当前电平
                                                            // debug_printf("btn:%d",btn->Button_Last_Level);
        btn->level_timercnt = 0;

        // add to line tabe
        add_button(btn);  // add button line

        return TRUE;
    }
    /**************************************************************************************************
     * function	:                                   Button_Attach
     * brief	:		attach button event to  corresponding button node
     * param	:  		button node||button event's array idex||button event's callback
     * return			:  TRUE FALSE
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    boolean_t button_attach(button_t * btn, Button_Event btn_event, Button_CallBack btn_callback)
    {
        uint8_t i = 0;
        if (btn == NULL)
        {
            return FALSE;
        }

        if (BUTTON_ALL_RIGGER == btn_event)
        {
            for (i = 0; i < number_of_event - 1; i++)
                btn->CallBack_Function[i] = btn_callback;  //
        }
        else
        {
            btn->CallBack_Function[btn_event] = btn_callback;  //
        }
        return TRUE;
    }

    /**************************************************************************************************
     * function	:                                   StrnCopy
     * brief	:
     * param	:  dst str || src str || str line
     * return			:  dst str
     * author			:  rinanfang  3/2/2020
     **************************************************************************************************/
    static char* strn_copy(char* dst, const char* src, uint32_t n)
    {
        if (n != 0)
        {
            char*       d = dst;
            const char* s = src;
            do
            {
                if ((*d++ = *s++) == 0)
                {
                    while (--n != 0)
                        *d++ = 0;
                    break;
                }
            } while (--n != 0);
        }
        return (dst);
    }
